// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraCharacter.h"

// 包含必要的头文件
#include "AbilitySystem/LyraAbilitySystemComponent.h"
#include "Camera/LyraCameraComponent.h"
#include "Character/LyraHealthComponent.h"
#include "Character/LyraPawnExtensionComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "LyraCharacterMovementComponent.h"
#include "LyraGameplayTags.h"
#include "LyraLogChannels.h"
#include "Net/UnrealNetwork.h"
#include "Player/LyraPlayerController.h"
#include "Player/LyraPlayerState.h"
#include "System/LyraSignificanceManager.h"
#include "TimerManager.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraCharacter)  // 包含生成的内联代码

class AActor;
class FLifetimeProperty;
class IRepChangedPropertyTracker;
class UInputComponent;

// 定义碰撞配置文件名称
static FName NAME_LyraCharacterCollisionProfile_Capsule(TEXT("LyraPawnCapsule"));
static FName NAME_LyraCharacterCollisionProfile_Mesh(TEXT("LyraPawnMesh"));

// 构造函数
ALyraCharacter::ALyraCharacter(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer.SetDefaultSubobjectClass<ULyraCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
{
    // 避免角色tick
    PrimaryActorTick.bCanEverTick = false;
    PrimaryActorTick.bStartWithTickEnabled = false;

    // 设置网络剔除距离
    NetCullDistanceSquared = 900000000.0f;

    // 初始化胶囊体组件
    UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
    check(CapsuleComp);
    CapsuleComp->InitCapsuleSize(40.0f, 90.0f);  // 设置胶囊体大小
    CapsuleComp->SetCollisionProfileName(NAME_LyraCharacterCollisionProfile_Capsule);  // 设置碰撞配置文件

    // 初始化网格体组件
    USkeletalMeshComponent* MeshComp = GetMesh();
    check(MeshComp);
    MeshComp->SetRelativeRotation(FRotator(0.0f, -90.0f, 0.0f));  // 旋转网格体使其X轴向前
    MeshComp->SetCollisionProfileName(NAME_LyraCharacterCollisionProfile_Mesh);

    // 初始化Lyra移动组件
    ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
    LyraMoveComp->GravityScale = 1.0f;                    // 重力缩放
    LyraMoveComp->MaxAcceleration = 2400.0f;              // 最大加速度
    LyraMoveComp->BrakingFrictionFactor = 1.0f;           // 制动摩擦因子
    LyraMoveComp->BrakingFriction = 6.0f;                 // 制动摩擦
    LyraMoveComp->GroundFriction = 8.0f;                  // 地面摩擦
    LyraMoveComp->BrakingDecelerationWalking = 1400.0f;   // 行走制动减速度
    LyraMoveComp->bUseControllerDesiredRotation = false;  // 不使用控制器期望旋转
    LyraMoveComp->bOrientRotationToMovement = false;      // 不朝向移动方向旋转
    LyraMoveComp->RotationRate = FRotator(0.0f, 720.0f, 0.0f);  // 旋转速率
    LyraMoveComp->bAllowPhysicsRotationDuringAnimRootMotion = false;  // 动画根运动期间不允许物理旋转
    LyraMoveComp->GetNavAgentPropertiesRef().bCanCrouch = true;  // 可以蹲下
    LyraMoveComp->bCanWalkOffLedgesWhenCrouching = true;  // 蹲下时可以走出边缘
    LyraMoveComp->SetCrouchedHalfHeight(65.0f);           // 蹲下时半高

    // 创建Pawn扩展组件
    PawnExtComponent = CreateDefaultSubobject<ULyraPawnExtensionComponent>(TEXT("PawnExtensionComponent"));
    PawnExtComponent->OnAbilitySystemInitialized_RegisterAndCall(FSimpleMulticastDelegate::FDelegate::CreateUObject(this, &ThisClass::OnAbilitySystemInitialized));
    PawnExtComponent->OnAbilitySystemUninitialized_Register(FSimpleMulticastDelegate::FDelegate::CreateUObject(this, &ThisClass::OnAbilitySystemUninitialized));

    // 创建生命值组件
    HealthComponent = CreateDefaultSubobject<ULyraHealthComponent>(TEXT("HealthComponent"));
    HealthComponent->OnDeathStarted.AddDynamic(this, &ThisClass::OnDeathStarted);      // 绑定死亡开始事件
    HealthComponent->OnDeathFinished.AddDynamic(this, &ThisClass::OnDeathFinished);    // 绑定死亡结束事件

    // 创建相机组件
    CameraComponent = CreateDefaultSubobject<ULyraCameraComponent>(TEXT("CameraComponent"));
    CameraComponent->SetRelativeLocation(FVector(-300.0f, 0.0f, 75.0f));  // 设置相对位置

    // 控制器旋转设置
    bUseControllerRotationPitch = false;  // 不使用控制器俯仰旋转
    bUseControllerRotationYaw = true;     // 使用控制器偏航旋转
    bUseControllerRotationRoll = false;    // 不使用控制器滚动旋转

    // 眼睛高度设置
    BaseEyeHeight = 80.0f;        // 基础眼睛高度
    CrouchedEyeHeight = 50.0f;    // 蹲下时眼睛高度
}

// 预初始化组件
void ALyraCharacter::PreInitializeComponents()
{
    Super::PreInitializeComponents();
}

// 开始游戏
void ALyraCharacter::BeginPlay()
{
    Super::BeginPlay();

    UWorld* World = GetWorld();

    // 检查是否需要注册到重要性管理器（非专用服务器）
    const bool bRegisterWithSignificanceManager = !IsNetMode(NM_DedicatedServer);
    if (bRegisterWithSignificanceManager)
    {
        if (ULyraSignificanceManager* SignificanceManager = USignificanceManager::Get<ULyraSignificanceManager>(World))
        {
            //@TODO: 注册对象到重要性管理器
            // SignificanceManager->RegisterObject(this, (EFortSignificanceType)SignificanceType);
        }
    }
}

// 结束游戏
void ALyraCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    Super::EndPlay(EndPlayReason);

    UWorld* World = GetWorld();

    // 从重要性管理器取消注册
    const bool bRegisterWithSignificanceManager = !IsNetMode(NM_DedicatedServer);
    if (bRegisterWithSignificanceManager)
    {
        if (ULyraSignificanceManager* SignificanceManager = USignificanceManager::Get<ULyraSignificanceManager>(World))
        {
            SignificanceManager->UnregisterObject(this);  // 取消注册对象
        }
    }
}

// 重置角色
void ALyraCharacter::Reset()
{
    DisableMovementAndCollision();  // 禁用移动和碰撞

    K2_OnReset();                   // 调用蓝图重置事件

    UninitAndDestroy();             // 反初始化和销毁
}

// 获取生命周期复制属性
void ALyraCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // 注册复制属性
    DOREPLIFETIME_CONDITION(ThisClass, ReplicatedAcceleration, COND_SimulatedOnly);  // 仅在模拟端复制加速度
    DOREPLIFETIME(ThisClass, MyTeamID)  // 复制团队ID
}

// 预复制处理
void ALyraCharacter::PreReplication(IRepChangedPropertyTracker& ChangedPropertyTracker)
{
    Super::PreReplication(ChangedPropertyTracker);

    // 压缩加速度数据用于网络复制
    if (UCharacterMovementComponent* MovementComponent = GetCharacterMovement())
    {
        const double MaxAccel = MovementComponent->MaxAcceleration;  // 最大加速度
        const FVector CurrentAccel = MovementComponent->GetCurrentAcceleration();  // 当前加速度
        double AccelXYRadians, AccelXYMagnitude;
        
        // 将笛卡尔坐标转换为极坐标
        FMath::CartesianToPolar(CurrentAccel.X, CurrentAccel.Y, AccelXYMagnitude, AccelXYRadians);

        // 量化加速度数据
        ReplicatedAcceleration.AccelXYRadians   = FMath::FloorToInt((AccelXYRadians / TWO_PI) * 255.0);     // [0, 2PI] -> [0, 255]
        ReplicatedAcceleration.AccelXYMagnitude = FMath::FloorToInt((AccelXYMagnitude / MaxAccel) * 255.0); // [0, MaxAccel] -> [0, 255]
        ReplicatedAcceleration.AccelZ           = FMath::FloorToInt((CurrentAccel.Z / MaxAccel) * 127.0);   // [-MaxAccel, MaxAccel] -> [-127, 127]
    }
}

// 通知控制器改变
void ALyraCharacter::NotifyControllerChanged()
{
    const FGenericTeamId OldTeamId = GetGenericTeamId();  // 保存旧团队ID

    Super::NotifyControllerChanged();

    // 基于控制器更新团队ID（仅在权威端）
    if (HasAuthority() && (Controller != nullptr))
    {
        if (ILyraTeamAgentInterface* ControllerWithTeam = Cast<ILyraTeamAgentInterface>(Controller))
        {
            MyTeamID = ControllerWithTeam->GetGenericTeamId();  // 从控制器获取团队ID
            ConditionalBroadcastTeamChanged(this, OldTeamId, MyTeamID);  // 条件广播团队改变
        }
    }
}

// 获取Lyra玩家控制器
ALyraPlayerController* ALyraCharacter::GetLyraPlayerController() const
{
    return CastChecked<ALyraPlayerController>(Controller, ECastCheckedType::NullAllowed);
}

// 获取Lyra玩家状态
ALyraPlayerState* ALyraCharacter::GetLyraPlayerState() const
{
    return CastChecked<ALyraPlayerState>(GetPlayerState(), ECastCheckedType::NullAllowed);
}

// 获取Lyra能力系统组件
ULyraAbilitySystemComponent* ALyraCharacter::GetLyraAbilitySystemComponent() const
{
    return Cast<ULyraAbilitySystemComponent>(GetAbilitySystemComponent());
}

// 获取能力系统组件
UAbilitySystemComponent* ALyraCharacter::GetAbilitySystemComponent() const
{
    return PawnExtComponent->GetLyraAbilitySystemComponent();  // 从Pawn扩展组件获取
}

// 能力系统初始化完成
void ALyraCharacter::OnAbilitySystemInitialized()
{
    ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent();
    check(LyraASC);

    HealthComponent->InitializeWithAbilitySystem(LyraASC);  // 用能力系统初始化生命值组件

    InitializeGameplayTags();  // 初始化游戏标签
}

// 能力系统反初始化
void ALyraCharacter::OnAbilitySystemUninitialized()
{
    HealthComponent->UninitializeFromAbilitySystem();  // 从能力系统反初始化生命值组件
}

// 被控制器拥有
void ALyraCharacter::PossessedBy(AController* NewController)
{
    const FGenericTeamId OldTeamID = MyTeamID;  // 保存旧团队ID

    Super::PossessedBy(NewController);

    PawnExtComponent->HandleControllerChanged();  // 处理控制器改变

    // 获取当前团队ID并监听未来变化
    if (ILyraTeamAgentInterface* ControllerAsTeamProvider = Cast<ILyraTeamAgentInterface>(NewController))
    {
        MyTeamID = ControllerAsTeamProvider->GetGenericTeamId();  // 从控制器获取团队ID
        ControllerAsTeamProvider->GetTeamChangedDelegateChecked().AddDynamic(this, &ThisClass::OnControllerChangedTeam);  // 绑定团队改变委托
    }
    ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);  // 条件广播团队改变
}

// 取消拥有
void ALyraCharacter::UnPossessed()
{
    AController* const OldController = Controller;  // 保存旧控制器

    // 停止监听旧控制器的变化
    const FGenericTeamId OldTeamID = MyTeamID;
    if (ILyraTeamAgentInterface* ControllerAsTeamProvider = Cast<ILyraTeamAgentInterface>(OldController))
    {
        ControllerAsTeamProvider->GetTeamChangedDelegateChecked().RemoveAll(this);  // 移除所有团队改变委托
    }

    Super::UnPossessed();

    PawnExtComponent->HandleControllerChanged();  // 处理控制器改变

    // 确定取消拥有后新的团队ID
    MyTeamID = DetermineNewTeamAfterPossessionEnds(OldTeamID);
    ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);  // 条件广播团队改变
}

// 复制控制器回调
void ALyraCharacter::OnRep_Controller()
{
    Super::OnRep_Controller();

    PawnExtComponent->HandleControllerChanged();  // 处理控制器改变
}

// 复制玩家状态回调
void ALyraCharacter::OnRep_PlayerState()
{
    Super::OnRep_PlayerState();

    PawnExtComponent->HandlePlayerStateReplicated();  // 处理玩家状态复制
}

// 设置玩家输入组件
void ALyraCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    PawnExtComponent->SetupPlayerInputComponent();  // 设置Pawn扩展组件的输入
}

// 初始化游戏标签
void ALyraCharacter::InitializeGameplayTags()
{
    // 清除可能残留在能力系统上的先前Pawn的标签
    if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        // 清除移动模式标签
        for (const TPair<uint8, FGameplayTag>& TagMapping : LyraGameplayTags::MovementModeTagMap)
        {
            if (TagMapping.Value.IsValid())
            {
                LyraASC->SetLooseGameplayTagCount(TagMapping.Value, 0);  // 设置松散游戏标签计数为0
            }
        }

        // 清除自定义移动模式标签
        for (const TPair<uint8, FGameplayTag>& TagMapping : LyraGameplayTags::CustomMovementModeTagMap)
        {
            if (TagMapping.Value.IsValid())
            {
                LyraASC->SetLooseGameplayTagCount(TagMapping.Value, 0);  // 设置松散游戏标签计数为0
            }
        }

        // 设置当前移动模式标签
        ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
        SetMovementModeTag(LyraMoveComp->MovementMode, LyraMoveComp->CustomMovementMode, true);  // 启用当前移动模式标签
    }
}

// 获取拥有的游戏标签
void ALyraCharacter::GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const
{
    if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        LyraASC->GetOwnedGameplayTags(TagContainer);  // 从能力系统获取拥有的标签
    }
}

// 检查是否匹配游戏标签
bool ALyraCharacter::HasMatchingGameplayTag(FGameplayTag TagToCheck) const
{
    if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        return LyraASC->HasMatchingGameplayTag(TagToCheck);  // 检查是否匹配标签
    }

    return false;
}

// 检查是否匹配所有游戏标签
bool ALyraCharacter::HasAllMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const
{
    if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        return LyraASC->HasAllMatchingGameplayTags(TagContainer);  // 检查是否匹配所有标签
    }

    return false;
}

// 检查是否匹配任何游戏标签
bool ALyraCharacter::HasAnyMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const
{
    if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        return LyraASC->HasAnyMatchingGameplayTags(TagContainer);  // 检查是否匹配任何标签
    }

    return false;
}

// 掉落出世界
void ALyraCharacter::FellOutOfWorld(const class UDamageType& dmgType)
{
    HealthComponent->DamageSelfDestruct(/*bFellOutOfWorld=*/ true);  // 自毁伤害
}

// 死亡开始
void ALyraCharacter::OnDeathStarted(AActor*)
{
    DisableMovementAndCollision();  // 禁用移动和碰撞
}

// 死亡结束
void ALyraCharacter::OnDeathFinished(AActor*)
{
    GetWorld()->GetTimerManager().SetTimerForNextTick(this, &ThisClass::DestroyDueToDeath);  // 下一帧销毁
}

// 禁用移动和碰撞
void ALyraCharacter::DisableMovementAndCollision()
{
    if (Controller)
    {
        Controller->SetIgnoreMoveInput(true);  // 设置忽略移动输入
    }

    UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
    check(CapsuleComp);
    CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);  // 禁用碰撞
    CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore);        // 忽略所有碰撞通道

    ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
    LyraMoveComp->StopMovementImmediately();  // 立即停止移动
    LyraMoveComp->DisableMovement();          // 禁用移动
}

// 因死亡而销毁
void ALyraCharacter::DestroyDueToDeath()
{
    K2_OnDeathFinished();  // 调用蓝图死亡结束事件

    UninitAndDestroy();    // 反初始化和销毁
}

// 反初始化和销毁
void ALyraCharacter::UninitAndDestroy()
{
    if (GetLocalRole() == ROLE_Authority)  // 仅在权威端执行
    {
        DetachFromControllerPendingDestroy();  // 从控制器分离等待销毁
        SetLifeSpan(0.1f);                    // 设置生命周期
    }

    // 如果仍然是化身角色，则反初始化ASC
    if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        if (LyraASC->GetAvatarActor() == this)
        {
            PawnExtComponent->UninitializeAbilitySystem();  // 反初始化能力系统
        }
    }

    SetActorHiddenInGame(true);  // 在游戏中隐藏角色
}

// 移动模式改变
void ALyraCharacter::OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode)
{
    Super::OnMovementModeChanged(PrevMovementMode, PreviousCustomMode);

    ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());

    // 更新移动模式标签
    SetMovementModeTag(PrevMovementMode, PreviousCustomMode, false);  // 禁用旧移动模式标签
    SetMovementModeTag(LyraMoveComp->MovementMode, LyraMoveComp->CustomMovementMode, true);  // 启用新移动模式标签
}

// 设置移动模式标签
void ALyraCharacter::SetMovementModeTag(EMovementMode MovementMode, uint8 CustomMovementMode, bool bTagEnabled)
{
    if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        const FGameplayTag* MovementModeTag = nullptr;
        
        // 根据移动模式查找对应的标签
        if (MovementMode == MOVE_Custom)
        {
            MovementModeTag = LyraGameplayTags::CustomMovementModeTagMap.Find(CustomMovementMode);  // 查找自定义移动模式标签
        }
        else
        {
            MovementModeTag = LyraGameplayTags::MovementModeTagMap.Find(MovementMode);  // 查找标准移动模式标签
        }

        // 设置标签计数
        if (MovementModeTag && MovementModeTag->IsValid())
        {
            LyraASC->SetLooseGameplayTagCount(*MovementModeTag, (bTagEnabled ? 1 : 0));  // 设置松散游戏标签计数
        }
    }
}

// 切换蹲下
void ALyraCharacter::ToggleCrouch()
{
    const ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());

    // 如果正在蹲下或想要蹲下，则取消蹲下
    if (bIsCrouched || LyraMoveComp->bWantsToCrouch)
    {
        UnCrouch();
    }
    // 如果在地面上移动，则蹲下
    else if (LyraMoveComp->IsMovingOnGround())
    {
        Crouch();
    }
}

// 开始蹲下
void ALyraCharacter::OnStartCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust)
{
    if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        LyraASC->SetLooseGameplayTagCount(LyraGameplayTags::Status_Crouching, 1);  // 设置蹲下状态标签
    }

    Super::OnStartCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust);
}

// 结束蹲下
void ALyraCharacter::OnEndCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust)
{
    if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
    {
        LyraASC->SetLooseGameplayTagCount(LyraGameplayTags::Status_Crouching, 0);  // 清除蹲下状态标签
    }

    Super::OnEndCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust);
}

// 检查是否可以跳跃（实现）
bool ALyraCharacter::CanJumpInternal_Implementation() const
{
    // 与ACharacter的实现相同，但没有蹲下检查
    return JumpIsAllowedInternal();
}

// 复制加速度回调
void ALyraCharacter::OnRep_ReplicatedAcceleration()
{
    if (ULyraCharacterMovementComponent* LyraMovementComponent = Cast<ULyraCharacterMovementComponent>(GetCharacterMovement()))
    {
        // 解压缩加速度数据
        const double MaxAccel         = LyraMovementComponent->MaxAcceleration;  // 最大加速度
        const double AccelXYMagnitude = double(ReplicatedAcceleration.AccelXYMagnitude) * MaxAccel / 255.0; // [0, 255] -> [0, MaxAccel]
        const double AccelXYRadians   = double(ReplicatedAcceleration.AccelXYRadians) * TWO_PI / 255.0;     // [0, 255] -> [0, 2PI]

        // 将极坐标转换回笛卡尔坐标
        FVector UnpackedAcceleration(FVector::ZeroVector);
        FMath::PolarToCartesian(AccelXYMagnitude, AccelXYRadians, UnpackedAcceleration.X, UnpackedAcceleration.Y);
        UnpackedAcceleration.Z = double(ReplicatedAcceleration.AccelZ) * MaxAccel / 127.0; // [-127, 127] -> [-MaxAccel, MaxAccel]

        LyraMovementComponent->SetReplicatedAcceleration(UnpackedAcceleration);  // 设置复制的加速度
    }
}

// 设置通用团队ID
void ALyraCharacter::SetGenericTeamId(const FGenericTeamId& NewTeamID)
{
    // 只能在无控制器时设置团队ID（在权威端）
    if (GetController() == nullptr)
    {
        if (HasAuthority())
        {
            const FGenericTeamId OldTeamID = MyTeamID;
            MyTeamID = NewTeamID;
            ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);  // 条件广播团队改变
        }
        else
        {
            UE_LOG(LogLyraTeams, Error, TEXT("You can't set the team ID on a character (%s) except on the authority"), *GetPathNameSafe(this));
        }
    }
    else
    {
        UE_LOG(LogLyraTeams, Error, TEXT("You can't set the team ID on a possessed character (%s); it's driven by the associated controller"), *GetPathNameSafe(this));
    }
}

// 获取通用团队ID
FGenericTeamId ALyraCharacter::GetGenericTeamId() const
{
    return MyTeamID;
}

// 获取团队索引改变委托
FOnLyraTeamIndexChangedDelegate* ALyraCharacter::GetOnTeamIndexChangedDelegate()
{
    return &OnTeamChangedDelegate;
}

// 控制器改变团队回调
void ALyraCharacter::OnControllerChangedTeam(UObject* TeamAgent, int32 OldTeam, int32 NewTeam)
{
    const FGenericTeamId MyOldTeamID = MyTeamID;
    MyTeamID = IntegerToGenericTeamId(NewTeam);  // 整数转换为通用团队ID
    ConditionalBroadcastTeamChanged(this, MyOldTeamID, MyTeamID);  // 条件广播团队改变
}

// 复制团队ID回调
void ALyraCharacter::OnRep_MyTeamID(FGenericTeamId OldTeamID)
{
    ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);  // 条件广播团队改变
}

// 更新共享复制
bool ALyraCharacter::UpdateSharedReplication()
{
    if (GetLocalRole() == ROLE_Authority)  // 仅在权威端执行
    {
        FSharedRepMovement SharedMovement;
        if (SharedMovement.FillForCharacter(this))  // 为角色填充共享移动数据
        {
            // 只有当数据自上一帧以来发生变化时才调用FastSharedReplication
            if (!SharedMovement.Equals(LastSharedReplication, this))
            {
                LastSharedReplication = SharedMovement;  // 更新最后共享复制数据
                ReplicatedMovementMode = SharedMovement.RepMovementMode;  // 更新复制移动模式

                FastSharedReplication(SharedMovement);  // 执行快速共享复制
            }
            return true;
        }
    }

    // 当前无法快速复制，不发送任何内容
    return false;
}

// 快速共享复制实现
void ALyraCharacter::FastSharedReplication_Implementation(const FSharedRepMovement& SharedRepMovement)
{
    if (GetWorld()->IsPlayingReplay())  // 回放期间不处理
    {
        return;
    }

    // 检查时间戳以拒绝旧的移动
    if (GetLocalRole() == ROLE_SimulatedProxy)  // 仅在模拟代理端处理
    {
        // 时间戳
        ReplicatedServerLastTransformUpdateTimeStamp = SharedRepMovement.RepTimeStamp;

        // 移动模式
        if (ReplicatedMovementMode != SharedRepMovement.RepMovementMode)
        {
            ReplicatedMovementMode = SharedRepMovement.RepMovementMode;
            GetCharacterMovement()->bNetworkMovementModeChanged = true;  // 标记移动模式改变
            GetCharacterMovement()->bNetworkUpdateReceived = true;       // 标记网络更新接收
        }

        // 位置、旋转、速度等
        FRepMovement& MutableRepMovement = GetReplicatedMovement_Mutable();
        MutableRepMovement = SharedRepMovement.RepMovement;

        // 这也设置了LastRepMovement
        OnRep_ReplicatedMovement();  // 调用复制移动回调

        // 跳跃力
        bProxyIsJumpForceApplied = SharedRepMovement.bProxyIsJumpForceApplied;

        // 蹲下状态
        if (bIsCrouched != SharedRepMovement.bIsCrouched)
        {
            bIsCrouched = SharedRepMovement.bIsCrouched;
            OnRep_IsCrouched();  // 调用蹲下状态复制回调
        }
    }
}

// FSharedRepMovement构造函数
FSharedRepMovement::FSharedRepMovement()
{
    RepMovement.LocationQuantizationLevel = EVectorQuantization::RoundTwoDecimals;  // 位置量化级别
}

// 为角色填充数据
bool FSharedRepMovement::FillForCharacter(ACharacter* Character)
{
    if (USceneComponent* PawnRootComponent = Character->GetRootComponent())
    {
        UCharacterMovementComponent* CharacterMovement = Character->GetCharacterMovement();

        // 填充复制移动数据
        RepMovement.Location = FRepMovement::RebaseOntoZeroOrigin(PawnRootComponent->GetComponentLocation(), Character);  // 基于零原点的位置
        RepMovement.Rotation = PawnRootComponent->GetComponentRotation();  // 旋转
        RepMovement.LinearVelocity = CharacterMovement->Velocity;          // 线性速度
        RepMovementMode = CharacterMovement->PackNetworkMovementMode();    // 打包网络移动模式
        bProxyIsJumpForceApplied = Character->bProxyIsJumpForceApplied || (Character->JumpForceTimeRemaining > 0.0f);  // 代理是否应用跳跃力
        bIsCrouched = Character->bIsCrouched;  // 是否蹲下

        // 如果未使用，时间戳发送为零
        if ((CharacterMovement->NetworkSmoothingMode == ENetworkSmoothingMode::Linear) || CharacterMovement->bNetworkAlwaysReplicateTransformUpdateTimestamp)
        {
            RepTimeStamp = CharacterMovement->GetServerLastTransformUpdateTimeStamp();  // 获取服务器最后变换更新时间戳
        }
        else
        {
            RepTimeStamp = 0.f;  // 时间戳为零
        }

        return true;
    }
    return false;
}

// 比较是否相等
bool FSharedRepMovement::Equals(const FSharedRepMovement& Other, ACharacter* Character) const
{
    // 比较各个字段是否相等
    if (RepMovement.Location != Other.RepMovement.Location)
    {
        return false;
    }

    if (RepMovement.Rotation != Other.RepMovement.Rotation)
    {
        return false;
    }

    if (RepMovement.LinearVelocity != Other.RepMovement.LinearVelocity)
    {
        return false;
    }

    if (RepMovementMode != Other.RepMovementMode)
    {
        return false;
    }

    if (bProxyIsJumpForceApplied != Other.bProxyIsJumpForceApplied)
    {
        return false;
    }

    if (bIsCrouched != Other.bIsCrouched)
    {
        return false;
    }

    return true;
}

// 网络序列化
bool FSharedRepMovement::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
    bOutSuccess = true;
    RepMovement.NetSerialize(Ar, Map, bOutSuccess);  // 序列化复制移动数据
    Ar << RepMovementMode;          // 序列化移动模式
    Ar << bProxyIsJumpForceApplied; // 序列化跳跃力应用状态
    Ar << bIsCrouched;              // 序列化蹲下状态

    // 时间戳（如果非零）
    uint8 bHasTimeStamp = (RepTimeStamp != 0.f);
    Ar.SerializeBits(&bHasTimeStamp, 1);  // 序列化是否有时间戳
    if (bHasTimeStamp)
    {
        Ar << RepTimeStamp;  // 序列化时间戳
    }
    else
    {
        RepTimeStamp = 0.f;  // 时间戳为零
    }

    return true;
}
